#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <algorithm>
#include <cstdlib>
#include <ctime>

using namespace std;

#define NULO 0
#define INF 999999999


void leerStdin();
list<int> ordenar_trabajos(int, vector< vector<int> >);
ostream& operator<<(ostream& os, list<int> lista);

timespec diff(timespec start, timespec end)
{
	timespec temp;
	if((end.tv_nsec - start.tv_nsec) < 0)
	{
		temp.tv_sec = end.tv_sec - start.tv_sec - 1;
		temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
	}
	else
	{
		temp.tv_sec = end.tv_sec - start.tv_sec;
		temp.tv_nsec = end.tv_nsec - start.tv_nsec;
	}
	return temp;
}

int main(int argc, char *argv[]) {
	
	timespec start, end, result;

	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
	
	leerStdin();

	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);

	result = diff(start, end);

	cout << result.tv_sec * (unsigned long) 1000000000 + result.tv_nsec << endl;

	return 0;
}

void leerStdin() {
	while(1) {
		int cantTrabajos = 0;
		if(!(cin >> cantTrabajos)) break;
		if(cantTrabajos == 0) break;
		int aux = 0;
		vector< vector<int> > matrizValores(cantTrabajos);
		for(int i = 0; i < cantTrabajos; i ++){
			for(int j = 0; j < (i + 1); j++){
					if(!(cin >> aux)) break;
					matrizValores[i].push_back(aux);
				}			
			}
		list<int> res = ordenar_trabajos(cantTrabajos, matrizValores);
		cout << res;
	}
}

list<int> ordenar_trabajos(int cantTrabajos, vector< vector<int> > matrizValores){
	
	int aux;
	int resultadoParcial[cantTrabajos][cantTrabajos];
	int log[cantTrabajos];
	
	resultadoParcial[0][0] = matrizValores[0][0];
	
	//Acá llena la matriz
	
	for(int i = 0; i < cantTrabajos - 1; i++){
	
			//Primero completa la fila que está recorriendo sumandole los trabajos uno atrás del otro	

			for(int a = i + 1; a < cantTrabajos; a++){
				resultadoParcial[i][a] = resultadoParcial[i][a - 1] + matrizValores[a][a];
			}

			//Después completa la primera casilla de la fila siguiente calculando los mínimos entre los valores de la columna i

			aux = INF;

			for(int k = i; k >= 0; k--) {
				if(aux > (resultadoParcial[k][i] + matrizValores[i + 1][k])) {
					aux = resultadoParcial[k][i] + matrizValores[i + 1][k];
					log[i + 1] = k;
				}
			}
				
			resultadoParcial[i + 1][i + 1] = aux;
				
	}

	
	//Acá encuentra el valor mínimo entre la última columna de la matriz
	
	aux = INF;
	int coordenada;
	int recorrer;
	int terminar;

	for(int j = 0; j < cantTrabajos; j++){
	
		if(aux > resultadoParcial[j][cantTrabajos - 1]){
			aux = resultadoParcial[j][cantTrabajos - 1];
			coordenada = j;
		}
	
	}



	//Acá reconstruye qué trabajo va en cada máquina

	list<int> resultado;
	log[0] = -1;
	recorrer = coordenada;
	terminar = log[coordenada];
	
	while(recorrer != -1 && terminar != -1){
		for(int c = recorrer; c > terminar; c--){
			resultado.push_front(c);		
		}
		
		recorrer = log[terminar];
		terminar = log[recorrer];	
	}
		
	
	resultado.push_front(resultado.size());
	resultado.push_front(aux);
	
	return resultado;	
}
	
ostream& operator<<(ostream& os, list<int> lista){
	
		list<int>::iterator it = lista.begin();
		int tam = lista.size();
			for (int a=0; a < tam; a++) {
			os << *it << " ";
			it++;
		}
		
		os << endl;
	
	
	}
